//看上界下界图片说明
package com.Generics4;

public class Main {
    public static void main(String[] args) {
        //定义了上界后，只能是Number类或Number的子类
        Score<Integer> score1 = new Score<Integer>("物理", 123, 123);

        // 泛型通配符也支持使用? extend Number设定泛型的界限
        Score<? extends Number> score2 = new Score<Integer>("化学", 124, 123);
        //一旦定义了上界，对象的泛型成员会变成上界的最顶层类型，这里是Number
        Number num = score2.getScore();  //用Number类型接收不报错，用Number的子类接受报错

        //同理，有上界就有下界，使用super指定下界，限定为匹配Integer及其父类，只有指定类型或其父类才能作为类型参数
        Score2<? super Integer> score3 = new Score2<Number>("地理", 125, 123);
        //一旦定义了下界，对象的泛型成员会变成下界的顶层类型，所有的下界上限都是Object,记得只有父类或相同类型才能接收子类
        Object num3 = score3.getScore();
        //上面只是提升到父类了，但使用的使用还是要转换成对应的类型，比如Integer
        Integer num4 = (Integer) num3;

        //反编译看下Score.class里，score被定义成Number类型，即验证了上面说的泛型的上界的接收的类型
        /*
        javap -l .\Score.class
        Compiled from "Score.java"
        public class com.Generics4.Score<S extends java.lang.Number> {
          public com.Generics4.Score(java.lang.String, int, S);
            LineNumberTable:
              line 14: 0
              line 15: 4
              line 16: 9
              line 17: 14
              line 18: 19
            LocalVariableTable:
              Start  Length  Slot  Name   Signature
                  0      20     0  this   Lcom/Generics4/Score;
                  0      20     1  name   Ljava/lang/String;
                  0      20     2    id   I
                  0      20     3 score   Ljava/lang/Number;

          public S getScore();
            LineNumberTable:
              line 21: 0
            LocalVariableTable:
              Start  Length  Slot  Name   Signature
                  0       5     0  this   Lcom/Generics4/Score;
        }

         */
    }
}
